package ongd.web;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import ongd.negocio.gestion.ControladorApadrinamiento;
import ongd.negocio.gestion.PersonaContacto;
import ongd.negocio.gestion.Proyecto;
import ongd.servicios.persistencia.exceptions.IllegalOrphanException;
import ongd.servicios.persistencia.exceptions.NonexistentEntityException;
import ongd.servicios.persistencia.exceptions.PreexistingEntityException;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;

/**
 * Clase que se encargará de listar los proyectos de apadrinamiento activos.
 *
 * @author <a href="mailto:egi0002@alu.ubu.es">Elena García Iglesias</a>
 * @author <a href="mailto:cms0021@alu.ubu.es">Cristina Martínez Sanz</a>
 * @version 1.0 20120124
 *
 */
@ManagedBean
@ViewScoped
public class Listado_ProyectoApadrinamiento extends ABean {

    /**
     * Objeto de tipo controlador de proyectos de apadrinamiento que nos permitirá acceder a los métodos
     * que nos permitan realizar las operaciones necesarias con los proyectos.
     */
    private ControladorApadrinamiento controlApadrin;
    /**
     * Objeto de tipo list que va a contener la lista de proyectos del tipo de proyecto
     * deseado y que estén activos que luego cargaremos.
     */
    private List<Proyecto> proyectos;
    /**
     * Objeto de tipo proyecto que va a guardar el valor del proyecto activo.
     */
    private Proyecto proyecto;
    /**
     * Booleano que indica si vamos a editar el proyecto.
     */
    private boolean editarProyecto;
    /**
     * Booleano que indica si vamos a editar a la persona de contacto.
     */
    private boolean editarPersionaContacto;
    /**
     * Booleano que indica si vamos a añadir una persona de contacto.
     */
    private boolean annadirPersonaContacto;
    /**
     * Boolean que indica si una persona de contacto ha sido modificada.
     */
    private boolean modificadaPersonaContacto;
    /**
     * Booleano que indica si hemos borrado una persona de contacto del proyecto.
     */
    private boolean borradaPersonaContacto;
    /**
     * Booleano que indica si hemos añadido una persona de contacto.
     */
    private boolean annadidaPersonaContacto;
    /**
     * Objeto de tipo persona de contacto que guarda el valor de la persona de contacto con la que estamos trabajando.
     */
    private PersonaContacto personaContacto;
    /**
     * Objeto de tipo lista de personas de contacto, que guarda la lista de personas de contacto que pertenecen a ese proyecto.
     */
    private List<PersonaContacto> personasContacto;
    /**
     * Objeto de tipo String que va a contener el título de la página donde
     * estemos.
     */
    private String titulo;

    /**
     * Constructo de la clase.
     */
    public Listado_ProyectoApadrinamiento() {
        SesionBean sesion = getSesionBean();
        if (sesion.iniciadaSesion()) {
            titulo = "Gestionar - Proyecto Apadrinamiento";
            controlApadrin = sesion.getControladorApadrinamiento();
            proyectos = new ArrayList<Proyecto>();
            proyecto = new Proyecto();
            proyecto.setTipo("AP");
            personaContacto = new PersonaContacto();
            personasContacto = new ArrayList<PersonaContacto>();
            proyectos = controlApadrin.obtenerProyectosApadrinamiento();
        }
    }

    /**
     * Método que carga las variables iniciales en función del modo de acceso a la página.
     */
    @Override
    public void cargaInicial() {
    }

    /**
     * Método que inicializa las variables cuando se desea editar un proyecto.
     * @return null.
     */
    public String editarProyecto() {
        editarProyecto = true;
        personasContacto.clear();
        personasContacto.addAll(proyecto.getPersonaContactoList());
        borradaPersonaContacto = false;
        annadidaPersonaContacto = false;
        return null;
    }

    /**
     * Método que inicializa las variables para consultar un proyecto.
     * @return null.
     */
    public String consultarProyecto() {
        editarProyecto = false;
        personasContacto.clear();
        personasContacto.addAll(proyecto.getPersonaContactoList());
        return null;
    }

    /**
     * Método que sube un archivo adjunto a la aplicación.
     * @param event Fichero a subir
     */
    public void subirAdjunto(FileUploadEvent event) {
        try {
            String nombre;
            SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
            nombre = sdf.format(new Date()) + "_" + event.getFile().getFileName();
            getSesionBean().guardar(nombre, event.getFile().getInputstream());
            proyecto.setDocumentoAdjunto(nombre);
        } catch (IOException ex) {
            Logger.getLogger(Insertar_Subvencion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Método que realiza las operaciones necesarias cuando se acepta la edición del proyecto.
     * @return null.
     */
    public String aceptarProyecto() {
        if (getSesionBean().iniciadaSesion()) {
            RequestContext requestContext = RequestContext.getCurrentInstance();
            //Si hemos dado a editar el proyecto
            try {
                //Miramos que todos los campos obligatorios tengan valor y si no es así no realizamos ninguna operación.   
                if (proyecto.getNombre().compareTo("") != 0 && proyecto.getPais().compareTo("") != 0
                        && proyecto.getResponsableONGD().compareTo("") != 0) {
                    if (editarProyecto) {
                        //Si hemos borrado alguna persona de contacto, borramos todas las personas de contacto de ese proyecto y creamos las de la lista                    
                        if (controlApadrin.editarProyecto(proyecto, personasContacto, modificadaPersonaContacto, annadidaPersonaContacto || borradaPersonaContacto)) {
                            requestContext.addCallbackParam("proyectoModif", true);
                            requestContext.addPartialUpdateTarget("form:panel");
                        } else {
                            requestContext.addCallbackParam("proyectoNoModif", true);
                        }
                    } else {
                        requestContext.addCallbackParam("consultar", true);
                    }
//                //Volvemos a cargar la lista de proyectos
//                proyectos=controlApadrin.obtenerProyectosApadrinamiento();
                } else {
                    requestContext.addCallbackParam("faltanDatos", true);
                    proyectos = new ArrayList<Proyecto>();
                    //Volvemos a cargar la lista de proyectos
                    proyectos = controlApadrin.obtenerProyectosApadrinamiento();
                }

            } catch (IllegalOrphanException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NonexistentEntityException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            } catch (PreexistingEntityException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }

    /**
     * Metodo que borra un proyecto de la base de datos y trata las personas de contacto y los apadrinados. 
     * relacionadas con este.
     * @return null.
     */
    public String borrarProyecto() {
        if (getSesionBean().iniciadaSesion()) {
            RequestContext requestContext = RequestContext.getCurrentInstance();
            try {
                if (controlApadrin.borrarProyecto(proyecto)) {
                    requestContext.addCallbackParam("proyectoBorrado", true);
                    //Volvemos a cargar la lista de proyectos
                    proyectos = controlApadrin.obtenerProyectosApadrinamiento();
                } else {
                    requestContext.addCallbackParam("proyectoNoBorrado", true);
                }
            } catch (IllegalOrphanException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NonexistentEntityException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }

    /**
     * Método que desactiva un proyecto.
     * @return null.
     */
    public String desactivarProyecto() {
        if (getSesionBean().iniciadaSesion()) {
            try {
                RequestContext requestContext = RequestContext.getCurrentInstance();
                if (controlApadrin.desactivarProyecto(proyecto)) {
                    requestContext.addCallbackParam("proyectoDesactivado", true);
                    proyectos = controlApadrin.obtenerProyectosApadrinamiento();
                } else {
                    requestContext.addCallbackParam("proyectoNoDesactivado", true);
                }
            } catch (IllegalOrphanException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NonexistentEntityException ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                Logger.getLogger(Listado_ProyectoApadrinamiento.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }

    /**
     * Método que inicializa las variables para editar una persona de contacto.
     * @return null.
     */
    public String editarPersonaContacto() {
        editarPersionaContacto = true;
        modificadaPersonaContacto = false;
        annadirPersonaContacto = false;
        return null;
    }

    /**
     * Método que inicializa las variables para permitir consultar una persona de contacto.
     * @return null.
     */
    public String consultarPersonaContacto() {
        editarPersionaContacto = false;
        annadirPersonaContacto = false;
        return null;
    }

    /**
     * Método que borra a una persona de contacto de la lista.
     * @return null.
     */
    public String borrarPersonaContacto() {
        //Si se ha elinimado de la lista
        if (personasContacto.remove(personaContacto)) {
            borradaPersonaContacto = true;
        }
        return null;
    }

    /**
     * Método que da valores a las variables para añadir una nueva persona de
     * contacto al proyecto.
     * @return null.
     */
    public String annadirPersonaContacto() {
        editarPersionaContacto = true;
        annadidaPersonaContacto = true;
        annadirPersonaContacto = true;
        personaContacto = new PersonaContacto();
        return null;
    }

    /**
     * Método que indica si se he modificado alguna persona se contacto y si se ha añadido alguna nueva la añade a la lista.
     * @return null.
     */
    public String aceptarPersonaContacto() {
        RequestContext requestContext = RequestContext.getCurrentInstance();
        if (personaContacto.getNombre().compareTo("") != 0 && personaContacto.getDireccion().compareTo("") != 0
                && personaContacto.getCargo().compareTo("") != 0 && personaContacto.getTelefono1().compareTo("") != 0) {
            if (editarPersionaContacto && !annadirPersonaContacto) {
                modificadaPersonaContacto = true;
            } else {
                if (editarPersionaContacto && annadirPersonaContacto) {
                    //Miramos si la persona de contacto tiene los datos obligatorios para insertarla
                    personasContacto.add(personaContacto);
                    annadidaPersonaContacto = true;
                }
            }
            requestContext.addPartialUpdateTarget("form:panel2");
            requestContext.addCallbackParam("personaC", true);
        } else {
            requestContext.addCallbackParam("personaNC", true);
        }

        return null;
    }

    /**
     * Método que indica si se ha añadido al menos una persona de contacto.
     * @return true si se ha añadido como mínimo una persona de contacto.
     *          false si no se ha añadido ninguna persona de contacto.
     */
    public boolean isAnnadidaPersonaContacto() {
        return annadidaPersonaContacto;
    }

    /**
     * Método que indica si hemos borrado una persona de contacto.
     * @return true si al menos hemos borrado una persona de contacto.
     *          false si no hemos borrado ninguna persona de contacto.
     */
    public boolean isBorradaPersonaContacto() {
        return borradaPersonaContacto;
    }

    /**
     * Método que devuelve el controlador de proyectos de apadrinamiento.
     * @return controlador de proyecto.
     * @see #setControlApadrin
     */
    public ControladorApadrinamiento getControlApadrin() {
        return controlApadrin;
    }

    /**
     * Método que nos dice si vamos a editar una persona de contacto.
     * @return true si vamsoa editar una persona de contacto.
     *          false si no la vamos a editar.
     */
    public boolean isEditarPersionaContacto() {
        return editarPersionaContacto;
    }

    /**
     * Método que nos indica si vamos a editar un proyecto.
     * @return true si vamos a editar un proyecto.
     *          false si no lo vamos a editar.
     */
    public boolean isEditarProyecto() {
        return editarProyecto;
    }

    /**
     * Metodo que indica si se ha modificado una persona de contacto.
     * @return true si al menos una persona se ha modificado.
     *          false si no se ha modificado ninguna.
     */
    public boolean isModificadaPersonaContacto() {
        return modificadaPersonaContacto;
    }

    /**
     * Método que devuelve la persona de contacto con la que estamos trabajando.
     * @return persona de contacto.
     * @see #setPersonaContacto
     */
    public PersonaContacto getPersonaContacto() {
        return personaContacto;
    }

    /**
     * Método que devuelve la lista de personas de contacto.
     * @return lista de personas de contacto.
     * @see #setPersonasContacto
     */
    public List<PersonaContacto> getPersonasContacto() {
        return personasContacto;
    }

    /**
     * Método que devuelve el proyecto con el que estamos trabajando.
     * @return proyecto.
     * @see #setProyecto
     */
    public Proyecto getProyecto() {
        return proyecto;
    }

    /**
     * Método que devuelve la lista de proyectos del tipo deseado que están activos.
     * @return null.
     * @see #setProyectos
     */
    public List<Proyecto> getProyectos() {
        return proyectos;
    }

    /**
     * Método que asigna un nuevo valor a la variable que indica si se ha añadido una nueva persona de contacto.
     * @param annadidaPersonaContacto nuevo valor de la variable. 
     */
    public void setAnnadidaPersonaContacto(boolean annadidaPersonaContacto) {
        this.annadidaPersonaContacto = annadidaPersonaContacto;
    }

    /**
     * Método que asigna un nuevo valor a la variable que indica si hemos borrado una persona de contacto.
     * @param borradaPersonaContacto nuevo valor d ela variable. 
     */
    public void setBorradaPersonaContacto(boolean borradaPersonaContacto) {
        this.borradaPersonaContacto = borradaPersonaContacto;
    }

    /**
     * Método que da un nuevo valor al controlador de proyecto de apadrinamiento.
     * @param controlApadrin nuevo valor del controlador. 
     * @see #getControlApadrin
     */
    public void setControlApadrin(ControladorApadrinamiento controlApadrin) {
        this.controlApadrin = controlApadrin;
    }

    /**
     * Método que da un nuevo valor a la variable que indica si vamos a editar a una persona de contacto.
     * @param editarPersionaContacto nuevo valor de la variable. 
     */
    public void setEditarPersionaContacto(boolean editarPersionaContacto) {
        this.editarPersionaContacto = editarPersionaContacto;
    }

    /**
     * Método que asigna un nuevo valor a la variable de editar un proyecto.
     * @param editarProyecto nuevo valor de la variable. 
     */
    public void setEditarProyecto(boolean editarProyecto) {
        this.editarProyecto = editarProyecto;
    }

    /**
     * Método que da un nuevo valor a la variable que indica si se ha modificao al menos una persona de contacto.
     * @param modificadaPersonaContacto nuevo valor de la variable. 
     */
    public void setModificadaPersonaContacto(boolean modificadaPersonaContacto) {
        this.modificadaPersonaContacto = modificadaPersonaContacto;
    }

    /**
     * Método que establece un nuevo valor para la persona de contacto.
     * @param personaContacto nueva persona de contacto. 
     * @see #getPersonaContacto
     */
    public void setPersonaContacto(PersonaContacto personaContacto) {
        this.personaContacto = personaContacto;
    }

    /**
     * Método que asigna un nuevo valor a la lista de personas de contacto.
     * @param personasContacto nuevo valor de la lista. 
     * @see #getPersonasContacto
     */
    public void setPersonasContacto(List<PersonaContacto> personasContacto) {
        this.personasContacto = personasContacto;
    }

    /**
     * Método que establece un nuevo valor para el proyecto.
     * @param proyecto nuevo proyecto. 
     * @see #getProyecto
     */
    public void setProyecto(Proyecto proyecto) {
        this.proyecto = proyecto;
    }

    /**
     * Método que establece un nuevo valor para la lista de proyectos.
     * @param proyectos nueva lista de proyectos. 
     * @see #getProyectos
     */
    public void setProyectos(List<Proyecto> proyectos) {
        this.proyectos = proyectos;
    }

    /**
     * Método que indica si vamos a añadir una persona de contacto.
     * @return true vamos a añadir una nueva persona de contacto
     *          false no vamos a añadir una nueva persona de contacto.
     */
    public boolean isAnnadirPersonaContacto() {
        return annadirPersonaContacto;
    }

    /**
     * Método que da un nuevo valor a la variable que indica si vamos a añadir una nueva persona de contacto.
     * @param annadirPersonaContacto nuevo valor de la variable. 
     */
    public void setAnnadirPersonaContacto(boolean annadirPersonaContacto) {
        this.annadirPersonaContacto = annadirPersonaContacto;
    }

    /**
     * Método que devuelve el valor de la variable titulo.
     * @return titulo
     * @see #setTitulo
     */
    public String getTitulo() {
        return titulo;
    }

    /**
     * Método que establece el valor de la variable título.
     * @param titulo Nuevo valor de la variable
     * @see #getTitulo
     */
    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }
}
